﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using Com.CloudTalk.Controller;

namespace Com.CloudTalk.Tests
{
    [TestFixture]
    public class CloudTalkTests
    {
        [SetUp]
        public void TestSetup()
        {
            CloudTalkController.ClearTables();
        }
        
        [Test]
        public void TestOneToOneRoom()
        {
            CTChatRoom room = CloudTalkController.CreateChatRoom("TestRoom");
            CTClient c = CloudTalkController.AddClient(room, "felipe.lima@gmail.com", "Felipe Lima", RoleTypes.Member);
            
            Assert.IsNotEmpty(room.ClientList);
            
            Assert.AreEqual(
                room.ClientList.FirstOrDefault().Email, 
                c.Email);
        }

        [Test]
        public void TestSingleMessage()
        {
            CTChatRoom room = CloudTalkController.CreateChatRoom("TestRoom");

            CTClient c1 = CloudTalkController.AddClient(room, "Felipe Lima", "felipe.lima@gmail.com", RoleTypes.Member);
            CTClient c2 = CloudTalkController.AddClient(room, "Tomás de Lara", "tomas@quavio.com.br", RoleTypes.Member);

            CloudTalkController.SendMessage(c1, "BlaBlaBla", c2.Email, room);

            Assert.IsNotEmpty(c1.SentMessages);

            //Assert.AreEqual(
            //    c1.SentMessages.FirstOrDefault().Text,
            //    "BlaBlaBla");

            List<CTEvent> msgsReceived = CloudTalkController.Receive(c2);

            Assert.IsNotEmpty(msgsReceived);

            CTEvent m = msgsReceived.FirstOrDefault();

            //Assert.AreEqual(m.Text,"BlaBlaBla");
            Assert.AreEqual(m.Sender.Name, "Felipe Lima");
            Assert.That(m.Type.GetType() == EventType.Message.GetType());

            msgsReceived = CloudTalkController.Receive(c2);

            Assert.IsEmpty(msgsReceived.ToList());

            msgsReceived = CloudTalkController.Receive(CloudTalkController.GetClientByEmail("felipe.lima@gmail.com"));

            Assert.IsNotEmpty(msgsReceived);
            
            m = msgsReceived.FirstOrDefault();

            Assert.AreEqual(m.Sender.Name, "Tomás de Lara");
            Assert.That(m.Type.GetType() == EventType.EnterRoom.GetType());
        }

        [Test]
        public void TestClearRoom()
        {
            CTChatRoom room = CloudTalkController.CreateChatRoom("TestRoom");

            CTClient c1 = CloudTalkController.AddClient(room, "Felipe Lima", "felipe.lima@gmail.com", RoleTypes.Member);
            CTClient c2 = CloudTalkController.AddClient(room, "Tomás de Lara", "tomas@quavio.com.br", RoleTypes.Member);

            Assert.IsNotEmpty(room.ClientList);

            CloudTalkController.ClearClients(room);

            Assert.IsEmpty(room.ClientList);
        }

        [Test]
        public void TestRemoveUser()
        {
            CTChatRoom room = CloudTalkController.CreateChatRoom("TestRoom");

            CTClient c1 = CloudTalkController.AddClient(room, "Felipe Lima", "felipe.lima@gmail.com", RoleTypes.Member);
            CloudTalkController.RemoveClient(room, "felipe.lima@gmail.com");
            
            Assert.IsEmpty(room.ClientList);
        }

        [Test]
        [ExpectedException(ExpectedException = typeof(FullChatRoomException))]
        public void TestRoomEnqueue()
        {
            CTChatRoom room = CloudTalkController.CreateChatRoom("TestRoom", 2);
            
            CTClient c1 = CloudTalkController.AddClient(room, "Felipe Lima", "felipe.lima@gmail.com", RoleTypes.Member);
            CTClient c2 = CloudTalkController.AddClient(room, "Tomás de Lara", "tomas@quavio.com.br", RoleTypes.Member);
            CTClient c3 = CloudTalkController.AddClient(room, "Ico Portela", "ico@quavio.com.br", RoleTypes.Member);

            Assert.AreEqual(CloudTalkController.RoomQueueSize(room), 1);
        }

        [Test]
        public void TestRoomDequeue()
        {
            CTChatRoom room = CloudTalkController.CreateChatRoom("TestRoom", 2);

            CTClient c1 = CloudTalkController.AddClient(room, "Felipe Lima", "felipe.lima@gmail.com", RoleTypes.Member);
            CTClient c2 = CloudTalkController.AddClient(room, "Tomás de Lara", "tomas@quavio.com.br", RoleTypes.Member);
            CTClient c3 = null;

            try
            {
                c3 = CloudTalkController.AddClient(room, "Ico Portela", "ico@quavio.com.br", RoleTypes.Member);
            }
            catch (FullChatRoomException) { }

            CloudTalkController.RemoveClient(room, c1);
            c3 = CloudTalkController.GetClientByEmail("ico@quavio.com.br");
            List<CTEvent> events = CloudTalkController.Receive(c3);

            Assert.IsNotEmpty(events);

            CTEvent firstEvent = events.FirstOrDefault();

            Assert.AreEqual(firstEvent.Type, EventType.RoomSpaceAvailable);
            Assert.AreEqual(CloudTalkController.RoomQueueSize(room), 0);
        }

        [Test]
        public void TestRoomQueueAdvanced()
        {
            CTChatRoom room = CloudTalkController.CreateChatRoom("TestRoom", 2);

            CTClient c1 = CloudTalkController.AddClient(room, "Felipe Lima", "felipe.lima@gmail.com", RoleTypes.Member);
            CTClient c2 = CloudTalkController.AddClient(room, "Tomás de Lara", "tomas@quavio.com.br", RoleTypes.Member);
            CTClient c3 = null;
            CTClient c4 = null;

            try
            {
                c3 = CloudTalkController.AddClient(room, "Ico Portela", "ico@quavio.com.br", RoleTypes.Member);
            }
            catch (FullChatRoomException) { }
            try
            {
                c4 = CloudTalkController.AddClient(room, "Ico Portela", "ico@quavio.com.br", RoleTypes.Member);
            }
            catch (FullChatRoomException) { }

            Assert.AreEqual(CloudTalkController.RoomQueueSize(room), 2);

            CloudTalkController.RemoveClient(room, c2);
            c3 = CloudTalkController.GetClientByEmail("ico@quavio.com.br");
            List<CTEvent> events = CloudTalkController.Receive(c3);

            Assert.AreEqual(CloudTalkController.RoomQueueSize(room), 1);

            CloudTalkController.SendMessage(c3, "BlaBlaBla", room);

            List<CTEvent> msgsReceived = CloudTalkController.Receive(c1);
            Assert.IsNotEmpty(msgsReceived);
            CTEvent m = msgsReceived.FirstOrDefault();
            Assert.NotNull(m);
        }

        [Test]
        public void TestRoomQueueAdvanced2()
        {
            CTChatRoom room = CloudTalkController.CreateChatRoom("TestRoom", 2);

            CTClient felipe = CloudTalkController.AddClient(room, "Felipe Lima", "felipe.lima@gmail.com", RoleTypes.Member);    // felipe entra
            CTClient tomas = CloudTalkController.AddClient(room, "Tomás de Lara", "tomas@quavio.com.br", RoleTypes.Member);     // tomas entra
            CTClient ico = null;
            CTClient nicolas = null;
            CTClient cleber = null;
            CTClient aloisio = null;

            try
            {
                ico = CloudTalkController.AddClient(room, "Ico Portela", "ico@quavio.com.br", RoleTypes.Member);    // ico na fila
            }
            catch (FullChatRoomException) { }

            Assert.AreEqual(CloudTalkController.RoomQueueSize(room), 1);

            CloudTalkController.RemoveClient(room, tomas);                      // tomas sai
            ico = CloudTalkController.GetClientByEmail("ico@quavio.com.br");    // ico entra no lugar
            List<CTEvent> events = CloudTalkController.Receive(ico);

            Assert.AreEqual(CloudTalkController.RoomQueueSize(room), 0);

            CloudTalkController.SendMessage(ico, "BlaBlaBla", room);

            List<CTEvent> msgsReceived = CloudTalkController.Receive(felipe);
            Assert.IsNotEmpty(msgsReceived);
            CTEvent m = msgsReceived.FirstOrDefault();
            Assert.NotNull(m);

            try { nicolas = CloudTalkController.AddClient(room, "Nicolas Iensen", "nicolas@quavio.com.br", RoleTypes.Member); } // nicolas na fila }
            catch (FullChatRoomException) { }

            nicolas = CloudTalkController.GetClientByEmail("nicolas@quavio.com.br");

            Assert.IsNotNull(nicolas);
            Assert.AreEqual(CloudTalkController.RoomQueueSize(room), 1);

            try { cleber = CloudTalkController.AddClient(room, "Cleber Hensel", "cleber@quavio.com.br", RoleTypes.Member); } // cleber na fila }
            catch (FullChatRoomException) { }

            cleber = CloudTalkController.GetClientByEmail("cleber@quavio.com.br");

            Assert.IsNotNull(cleber);
            Assert.AreEqual(2, CloudTalkController.RoomQueueSize(room));

            try { aloisio = CloudTalkController.AddClient(room, "Aloisio Dias", "aloisio@quavio.com.br", RoleTypes.Member); } // aloisio na fila }
            catch (FullChatRoomException) { }

            aloisio = CloudTalkController.GetClientByEmail("aloisio@quavio.com.br");

            Assert.IsNotNull(aloisio);
            Assert.AreEqual(3, CloudTalkController.RoomQueueSize(room));

            CloudTalkController.RemoveClient(room, felipe);                             // felipe sai
            nicolas = CloudTalkController.GetClientByEmail("nicolas@quavio.com.br");    // nicolas entra no lugar
            CloudTalkController.SendMessage(nicolas, "LaLaRi", room);
            Assert.AreEqual(2, CloudTalkController.RoomQueueSize(room));

            cleber = CloudTalkController.GetClientByEmail("cleber@quavio.com.br");
            msgsReceived = CloudTalkController.Receive(cleber);
            Assert.IsNotEmpty(msgsReceived);
            m = msgsReceived.FirstOrDefault();
            Assert.NotNull(m);
            Assert.AreEqual(m.Type, EventType.QueueSizeChanged);

            aloisio = CloudTalkController.GetClientByEmail("aloisio@quavio.com.br");
            msgsReceived = CloudTalkController.Receive(aloisio);
            Assert.IsNotEmpty(msgsReceived);
            m = msgsReceived.FirstOrDefault();
            Assert.NotNull(m);
            Assert.AreEqual(m.Type, EventType.QueueSizeChanged);
        }

        [Test]
        public void TestAbandonQueue()
        {
            CTChatRoom room = CloudTalkController.CreateChatRoom("TestRoom", 2);

            CTClient felipe = CloudTalkController.AddClient(room, "Felipe Lima", "felipe.lima@gmail.com", RoleTypes.Member);    // felipe entra
            CTClient tomas = CloudTalkController.AddClient(room, "Tomás de Lara", "tomas@quavio.com.br", RoleTypes.Member);     // tomas entra
            CTClient ico = null;
            CTClient nicolas = null;

            try { ico = CloudTalkController.AddClient(room, "Ico Portela", "ico@quavio.com.br", RoleTypes.Member); }  // ico na fila }
            catch (FullChatRoomException) { }

            try { nicolas = CloudTalkController.AddClient(room, "Nicolas Iensen", "nicolas@quavio.com.br", RoleTypes.Member); } // nicolas na fila }
            catch (FullChatRoomException) { }

            ico = CloudTalkController.GetClientByEmail("ico@quavio.com.br");
            CloudTalkController.RemoveClient(room, ico);

            Assert.AreEqual(1, CloudTalkController.RoomQueueSize(room));
        }
    }
}
